<?php
/**
 * Project:     Rebel PHP Framework
 * File:        Rebel_Loader.php
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * @link http://www.rebelphpframework.org
 * @copyright 2007 Emanuele Colonnelli
 * @author Emanuele Colonnelli <emanuele.colonnelli at gmail dot com>
 * @package kernel
 * @version 1.0
 */


if(define(__FILE__,true)) {

	function debug($var) {
		echo "<pre>";
		print_r($var);
		echo "</pre>";
	}
	
	$url = new Rebel_Net_Util_URL($_SERVER['HTTP_HOST']);
	define('MAP_PATH',sprintf('%s/.rebel/map/sitemap.xml',$_SERVER['DOCUMENT_ROOT']));
	define('MAP_SCOPE',$_SERVER['HTTP_HOST']);
	
	class Rebel_Loader {
		
		private static $instance;
		
		private function __construct() {
			self::$instance = $this;
			self::init();
		}//:-

		
		/**
		 * @return Rebel_Loader
		 */
		public static function instance() {
			return self::$instance ? self::$instance : new self;
		}//:-
		
		
		private static function invoke($node) {
			
			if('xmap:default' == $node->nodeName) {
				
				echo "DEFAULT";
				
			}

			if('xmap:class' == $node->nodeName) {
				
				if($node->getAttribute('type') == 'static')
				{
					$args = array();
					if($params = $node->getAttribute('params')) {
						
						$tp = explode(';',$params);
						
						foreach ($tp as $v) {
							$h = explode(':',$v);
							switch ($h[0]) {
								case 'cookie':
								case 'get':
								case 'post':
								case 'request':
								case 'session':
									$k = sprintf('_%s',strtoupper($h[0]));
									
									if($var = Rebel_Net_Http_Request::get($h[1],$k)) {
										array_push($args,$var);
									} else {
										switch ($h[0]) {
											case 'cookie':
												$errorCode = Rebel_LoaderException::MSG_COOKIE_REQUIRED;
												break;
											case 'get':
												$errorCode = Rebel_LoaderException::MSG_GET_REQUIRED;
												break;
											case 'post':
												$errorCode = Rebel_LoaderException::MSG_POST_REQUIRED;
												break;
											case 'request':
												$errorCode = Rebel_LoaderException::MSG_REQUEST_REQUIRED;
												break;
											case 'session':
												$errorCode = Rebel_LoaderException::MSG_SESSION_REQUIRED;
												break;
										}
										throw new Rebel_LoaderException($errorCode,$h[1]);
									}
									unset($var);
									break;
								default:
									if(empty($h[1])) {
										throw new Rebel_LoaderException(Rebel_LoaderException::MSG_PARAM_REQUIRED,$h[0]);
									} else {
										array_push($args,$h[1]);
									}
									break;
							}
							
							
						}
					}

					try {
						
						/**
						 * Check if class and method exist, else throws an exception
						 */
						$r = new ReflectionClass($node->getAttribute('name'));
						$r->getMethod($node->getAttribute('method'));
						
						call_user_func_array(array($node->getAttribute('name'),$node->getAttribute('method')),$args);

					} catch (Exception $e) {
					
						die(print_r($e->getMessage(),1));
							
					}
					
				} else {
					$o = new ${$node->getAttribute('name')};
					$o->{$node->method}();
				}
			}
			
		}//:-
		
		
		private static function init() {
			
			$doc = new DOMDocument();
			$doc->load(MAP_PATH);
			
			$xpath = new DOMXPath($doc);
			$xpath->registerNameSpace('xmap',sprintf('http://%s/xmap',MAP_SCOPE));
			
			$url = new Rebel_Net_Util_URL();
			
			$i = 1;
			$path_array = array();
			$qpath = "";
			while($j = $url->{$i++})
			{
				$part = "xmap:uri[@match = '{$j}']";
				$qpath.= '/'.$part;
				array_push($path_array,$part);
			}

			$query = "/xmap:site{$qpath}/xmap:class";
			
			$i = count($path_array);
			do {
				$path = implode('/',array_slice($path_array,0,$i--));
				$path = trim($path) ? $path.'/' : null;
				$nodes = $xpath->query('/xmap:site/'.$path.'xmap:class');
			}
			while( (1 > $nodes->length) && ($i >= 0));
			
			//default operation, when there aren't mapped uris
			if(!$nodes->length) {
				$query = '/xmap:site/xmap:default/xmap:class';
				$nodes = $xpath->query($query);
			}
			
			foreach($nodes as $node)
			{
				switch($node->nodeName) {
					case 'xmap:class':
						try {
							$q = "/xmap:site/{$path}ancestor-or-self::*[@auth = 'yes']";
							$checkAuth = $xpath->query($q);

							foreach ($checkAuth as $item) {
								if($item) {
									Rebel_Loader_Plugins_Auth::execute($item);
								}
							}
							
							self::invoke($node);
						} catch (Exception $e) {
							print_r($e);
						}
						break;
					case 'xmap:style':
						break;
				}
			}
			
		}//:-
		
	}///:-
	
	class Rebel_LoaderException extends Exception {
		
		const MSG_POST_REQUIRED = 1;
		const MSG_GET_REQUIRED = 2;
		const MSG_COOKIE_REQUIRED = 3;
		const MSG_SESSION_REQUIRED = 4;
		const MSG_REQUEST_REQUIRED = 5;
		const MSG_PARAM_REQUIRED = 6;
		const MSG_AUTHCLASS_NOTFOUND = 7;
		
		private static $messages = array(
			self::MSG_POST_REQUIRED => 'POST variable "%s" required!',
			self::MSG_GET_REQUIRED => 'GET variable "%s" required!',
			self::MSG_COOKIE_REQUIRED => 'COOKIE variable "%s" required!',
			self::MSG_SESSION_REQUIRED => 'SESSION variable "%s" required!',
			self::MSG_REQUEST_REQUIRED => 'REQUEST variable "%s" required!',
			self::MSG_PARAM_REQUIRED => 'STATIC paramater "%s" required. Please check your sitemap.xml file!',
			self::MSG_AUTHCLASS_NOTFOUND => 'AUTH CLASS %s NOT FOUND'
		);
		
		public function __construct($code=null,$paramName) {
			$message = isset(self::$messages[$code]) ? sprintf(self::$messages[$code],$paramName) : 'Unknown Exception';
			throw new Exception($message,$code);
		}//:-
		
		
		
	}///:-
}
?>